package com.itcam.maker.generator.file;

import cn.hutool.core.io.FileUtil;
import com.itcam.maker.meta.Meta;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * 动态文件生成
 */
public class DynamicFileGenerator {

    /**
     * 使用相对路径生成文件
     *
     * 这个方法通过相对路径来加载 Freemarker 模板文件，然后根据给定的数据模型生成文件并输出到指定路径。
     *
     * @param relativeInputPath 相对输入路径，用于指定模板文件的位置
     * @param outputPath        输出路径，生成的文件将保存到这个位置
     * @param model             数据模型，包含模板中需要替换的动态数据
     * @throws
     * @throws
     */
    public static void doGenerate(String relativeInputPath, String outputPath, Object model) throws IOException, TemplateException {
        // 🛠️ 先创建一个 Freemarker 的 Configuration 对象，就像给 Freemarker 设定一个版本号一样，这里用的是 2.3.32 版本
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);

        // 🗡️ 找到相对输入路径中最后一个斜杠的位置，就像给路径“切一刀”，为后面分割路径做准备
        int lastSplitIndex = relativeInputPath.lastIndexOf("/");
        // 📂 从路径开头到“切一刀”的位置，截取出来就是模板文件所在的基础包路径啦
        String basePackagePath = relativeInputPath.substring(0, lastSplitIndex);
        // 📄 从“切一刀”的位置往后，就是模板文件的名字啦
        String templateName = relativeInputPath.substring(lastSplitIndex + 1);

        // 🔍 嘿，这里要指定模板文件的位置啦！
        // 使用 ClassTemplateLoader 来加载模板文件，它就像一个小侦探，会从 DynamicFileGenerator 类的类路径下查找模板文件
        // basePackagePath 就是小侦探要找的基础路径哦
        ClassTemplateLoader templateLoader = new ClassTemplateLoader(DynamicFileGenerator.class, basePackagePath);
        // 📡 把这个小侦探（templateLoader）告诉 Freemarker 的配置对象（configuration），这样 Freemarker 就能找到模板文件啦
        configuration.setTemplateLoader(templateLoader);

        // 🌐 给模板文件设置一个字符集，就像给文件定一个“语言规则”，这里用的是 UTF-8
        configuration.setDefaultEncoding("utf-8");

        // 🏠 好啦，现在根据模板名字创建一个模板对象，就像根据图纸造出一个模板房子一样
        Template template = configuration.getTemplate(templateName);

        // 🪄 检查一下输出文件存不存在，如果不存在，那就像变魔术一样把它和它的父目录都创建出来
        if (!FileUtil.exist(outputPath)) {
            FileUtil.touch(outputPath);
        }

        // 🖋️ 准备开始生成文件啦，创建一个文件写入器，就像拿了一支笔准备往文件里写字
        Writer out = new FileWriter(outputPath);
        // 🏭 把数据模型和模板结合起来，用模板处理数据，就像把材料放进模具里做出成品一样
        template.process(model, out);

        // ✒️ 生成文件完成啦，别忘了把笔放下，也就是关闭文件写入器哦
        out.close();
    }

    /**
     * 生成文件
     *
     * @param inputPath  模板文件输入路径
     * @param outputPath 输出路径
     * @param model      数据模型
     * @throws IOException
     * @throws TemplateException
     */
    @Deprecated
    public static void doGenerateByPath(String inputPath, String outputPath, Object model) throws IOException, TemplateException {
        // new 出 Configuration 对象，参数为 FreeMarker 版本号
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_32);

        // 指定模板文件所在的路径
        File templateDir = new File(inputPath).getParentFile();
        configuration.setDirectoryForTemplateLoading(templateDir);

        // 设置模板文件使用的字符集
        configuration.setDefaultEncoding("utf-8");

        // 创建模板对象，加载指定模板
        String templateName = new File(inputPath).getName();
        Template template = configuration.getTemplate(templateName);

        // 文件不存在则创建文件和父目录
        if (!FileUtil.exist(outputPath)) {
            FileUtil.touch(outputPath);
        }

        // 生成
        Writer out = new FileWriter(outputPath);
        template.process(model, out);

        // 生成文件后别忘了关闭哦
        out.close();
    }

    /**
     * 生成代码的方法，该方法目前未使用传入的参数，也未抛出声明的异常。
     *
     * @param meta 元数据对象，目前未使用
     * @param outputPath 输出路径，目前未使用
     * @throws IOException 该异常在方法中未被抛出
     * @throws TemplateException 该异常在方法中未被抛出
     */
    protected void generateCode(Meta meta, String outputPath) throws IOException, TemplateException {
        // 定义输入资源路径，初始化为空字符串，目前未使用
        String inputResourcePath = "";
    }


}
